<template>
  <div>
    <el-dialog
      draggable
      :close-on-click-modal="false"
      v-model="dialogVisible"
      title="角色管理"
      width="480px"
      center
    >
      <el-form
        ref="formRef"
        :model="formValue"
        :rules="rules"
        label-width="80px"
        class="demo-ruleForm"
        status-icon
      >
        <el-form-item label="角色名称" prop="name">
          <el-input v-model="formValue.name" placeholder="角色名称"></el-input>
        </el-form-item>
        <el-form-item label="角色描述" prop="notes">
          <el-input
            v-model="formValue.notes"
            type="textarea"
            :rows="3"
            placeholder="角色描述"
          ></el-input>
        </el-form-item>

        <el-row>
          <el-col :span="12">
            <el-form-item label="状态" prop="enable">
              <el-switch
                v-model="formValue.enable"
                style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
                inline-prompt
                active-text="启用"
                inactive-text="停用"
              ></el-switch>
            </el-form-item>
          </el-col>
        </el-row>

        <el-form-item label="角色权限" prop="roles">
          <el-tree
            ref="treeRef"
            :data="treeList"
            show-checkbox
            node-key="value"
            :default-checked-keys="defaultcheckedkeys"
            @check="currentChecked"
            style="width: 350px; height: 200px; overflow-y: auto"
          >
          </el-tree>
        </el-form-item>

        <div style="text-align: center" v-has="['roles:add', 'roles:edit']">
          <el-button type="primary" auto-insert-space @click="submit(formRef)"> 保存 </el-button>
          <el-button @click="reset" auto-insert-space>重置</el-button>
        </div>
      </el-form>
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import { reactive, ref, onActivated } from 'vue'
import type { FormInstance, FormRules, ElMessage, ElMessageBox, ElTree } from 'element-plus'
import { sysroleSave, sysroleUpdateById, sysrolegetById, selectOneByName } from '@/apis/roles.js'
import { getSysMenuListTreeAll } from '@/apis/menu.js'

interface RuleForm {
  no: string
  name: string
  notes: string
  enable: true
  roles: []
}

interface Tree {
  value: number
  label: string
  children?: Tree[]
}

const formRef = ref()
let formValue = ref<RuleForm>({
  no: '',
  name: '',
  notes: '',
  enable: true,
  roles: []
})

let defaultcheckedkeys = ref()

const validateName = (rule: any, value: any, callback: any) => {
  const reg = /^[\u4e00-\u9fa5_a-zA-Z0-9_]{2,12}$/
  if (!reg.test(value)) {
    callback(new Error('长度在2~12位，只能包含中文、字母、数字、下划线'))
  } else {
    //新增操作再去判断 code 是否唯一
    selectOneByName(value, formValue.value.no)
      .then(function (response) {
        if (response != null) {
          callback(new Error('角色名称已存在'))
        } else {
          callback()
        }
      })
      .catch(function (error) {
        console.log(error)
      })
  }
}

let rules = reactive<FormRules>({
  name: [
    { required: true, message: '请输入角色名称', trigger: 'blur' },
    { min: 1, max: 12, message: '长度在1~12位字符', trigger: 'blur' },
    { validator: validateName }
  ],
  roles: [{ required: true, message: '请选择角色权限', trigger: 'change' }]
})

let dialogVisible = ref(false)

let originValue = {}

let treeRef = ref<InstanceType<typeof ElTree>>()
let oldRoles = []

function open(no) {
  oldRoles = []

  dialogVisible.value = true

  if (no != undefined && no != null) {
    sysrolegetById({
      no
    })
      .then(function (response) {
        formValue.value = response
        oldRoles = response.roles
        treeRef.value!.setCheckedKeys(response.roles)
        originValue = JSON.parse(JSON.stringify(response))
      })
      .catch(function (error) {
        console.log(error)
      })
  } else {
    let v = {
      no: '',
      name: '',
      notes: '',
      enable: true,
      roles: []
    }

    formValue.value = v
    originValue = JSON.parse(JSON.stringify(v))
  }

  reset()
}

function reset() {
  if (!formRef) return
  formRef.value.resetFields()
  formValue.value = JSON.parse(JSON.stringify(originValue))

  treeRef.value!.setCheckedKeys(oldRoles)
}

const emit = defineEmits(['getPage'])

function baoCun() {
  ElMessageBox.confirm('确定要保存吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  })
    .then(() => {
      if (formValue.value.no == '') {
        sysroleSave(formValue.value)
          .then(function (response) {
            if (response) {
              ElMessage({
                type: 'success',
                message: '保存成功'
              })

              dialogVisible.value = false

              emit('getPage')
            }
          })
          .catch(function (error) {
            console.log(error)
          })
      } else if (formValue.value.no != null) {
        sysroleUpdateById(formValue.value)
          .then(function (response) {
            if (response) {
              ElMessage({
                type: 'success',
                message: '保存成功'
              })

              dialogVisible.value = false
              emit('getPage')
            }
          })
          .catch(function (error) {
            console.log(error)
          })
      }
    })
    .catch(() => {
      ElMessage({
        type: 'info',
        message: '取消保存'
      })
    })
}

function currentChecked(nodeObj, SelectedObj) {
  let fullcheck = SelectedObj.checkedNodes.map((item) => item.value)

  formValue.value.roles = fullcheck
  defaultcheckedkeys.value = fullcheck
}

const submit = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid, fields) => {
    if (valid) {
      baoCun()
    } else {
      console.log('error submit!', fields)
    }
  })
}

let treeList = reactive([])

function getListTree() {
  getSysMenuListTreeAll()
    .then((response) => {
      treeList = []

      response.forEach((element) => {
        let obj = {
          value: element.id,
          label: element.name,
          children: []
        }

        if (element.children != undefined && element.children.length > 0) {
          element.children.forEach((children) => {
            let childrenobj = {
              value: children.id,
              label: children.name,
              children: []
            }

            if (children.children != undefined && children.children.length > 0) {
              children.children.forEach((child) => {
                childrenobj.children.push({
                  value: child.id,
                  label: child.name
                })
              })
            }

            obj.children.push(childrenobj)
          })
        }

        treeList.push(obj)
      })
    })
    .catch((error) => {
      console.log(error)
    })
}

onActivated(() => {
  getListTree()
})

defineExpose({ open })
</script>

<style lang="scss" scoped></style>
